﻿#include "Camera.h"

FCamera::FCamera(const glm::vec3& Position, const glm::vec3& WorldUp)
	: Position(Position)
	, WorldUp(WorldUp)
{
	this->UpdateCameraVectors();
}

glm::mat4 FCamera::GetViewMat() const
{
	const_cast<FCamera*>(this)->UpdateCameraVectors();
	return glm::lookAt(Position, Position + Front, Up);
}

const glm::vec3& FCamera::GetRightVector() const
{
	const_cast<FCamera*>(this)->UpdateCameraVectors();
	return Right;
}

const glm::vec3& FCamera::GetFrontVector() const
{
	const_cast<FCamera*>(this)->UpdateCameraVectors();
	return Front;
}

void FCamera::AddYawOffset(const float YawOffset)
{
	Yaw += YawOffset;
	VectorIsDirty = true;
}

void FCamera::AddPitchOffset(const float PitchOffset)
{
	Pitch += PitchOffset;
	Pitch = glm::clamp(Pitch, -89.f, 89.f); 
	VectorIsDirty = true;
}

void FCamera::UpdateCameraVectors()
{
	if (!VectorIsDirty)
	{
		return;
	}

	// 本质上是从 球坐标系 转到 笛卡尔 坐标系
	// 公式			https://en.wikipedia.org/wiki/Spherical_coordinate_system
	// 推导过程		https://youtu.be/FLQXW6G9P8I?t=2126  
	glm::vec3 MyFront;
	MyFront.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
	MyFront.y = sin(glm::radians(Pitch));
	MyFront.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
	Front = glm::normalize(MyFront);

	// 叉乘
	Right = glm::normalize(glm::cross(MyFront, WorldUp));
	Up = glm::normalize(glm::cross(Right, MyFront));

	VectorIsDirty = false;
}
